package serverDB;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import search.TagedFiles;

/**
 * this class managing the access to the server database
 * @author ran
 *
 */
public class ConnectToDataBase {
	private static ConnectToDataBase inst = new ConnectToDataBase();

	Session session;
	/*
	 * constructor of the class
	 */
	private ConnectToDataBase() {
		java.io.File f = new java.io.File("C:\\Program Files\\project\\hibernate.cfg.xml");
		SessionFactory sessionFactory = new Configuration().configure(f).buildSessionFactory(); 
		session = sessionFactory.openSession(); 
	}
	/**
	 * 
	 * @return instance of the class
	 */
	public static ConnectToDataBase getInst() {
		return inst;
	}
	/**
	 * 
	 * @return the member session
	 */
	public Session getSession() {
		return session;
	}
	/**
	 * 
	 * @param userName name of client
	 * @param pass password of client
	 * @return Client instance of that user if exist
	 */
	public Client getClient(String userName, String pass) {

		Client client=null;
		Query query = session.createQuery("from Client where user_name= :user_name and password= :pass" );
		query.setParameter("user_name", userName);
		query.setParameter("pass", pass);
		List<Client> list = query.list();
		client = list.get(0);
		System.out.println("id: \t\t"+client.getUserId());
		System.out.println("Name: \t\t"+client.getUserName());
		System.out.println("Password: \t"+client.getPassword());
		System.out.println("email: \t"+client.getUserEmail());


		return client;
	}
	/**
	 * send query to DB
	 * @param queryToSearch the query we want to send
	 * @return list of Clients that answer to the quary
	 */
	public List<Client> getClient2(String queryToSearch) {

		Client client=null;
		Query query = session.createQuery(queryToSearch);
		List<Client> list = query.list();
		Iterator<Client> it=list.iterator();
		while(it.hasNext()){
			System.out.println("while");
			client = it.next();
			System.out.println("userName : "+client.getUserName());
		}
		if(list.isEmpty())
			return null;
		return list;
	}
	/**
	 * find file in database
	 * @param checkSum identifier of file
	 * @return list of file that return from the query
	 */
	public List<File> getFile(long checkSum) {
		Query query = session.createQuery("from File where checkSum= :check_sum");
		query.setParameter("check_sum", checkSum);
		List<File> list = query.list();
		if(list.isEmpty())
			return null;
		return list;
	}
	/**
	 * delete file from db
	 * @param file file instance to delete
	 * @return success or failure
	 */
	public boolean deleteFile(File file) {
		long curCheckSum=file.getCheckSum();
		FileManager fManager = new FileManager(session);
		fManager.delete(file);

		session.flush();
		List<File> sameCheckSumList=getFile(curCheckSum);
		if(sameCheckSumList!=null && sameCheckSumList.size()>0){
			System.out.println("sameCheckSumList is not empty");
			return false;
		}
		return true;

	}
	/**
	 * create new file in DB
	 * @param fileName the file name
	 * @param location location of file
	 * @param checkSum identifier of file
	 * @param box folder name that contain this folder
	 * @param modDate last modified date of file
	 * @param tagedFiles tag list of the file
	 * @return File instance
	 */
	public File createFile(String fileName, String location, Long checkSum,Box box,Date modDate, ArrayList<TagedFiles> tagedFiles) {
		System.out.println("@#%#$^$^&*%^&*^&*%$@#$@$#$^$%^");
		System.out.println("file name : "+ fileName);
		System.out.println("location : "+ location);
		System.out.println("checkSum : "+ checkSum);
		System.out.println("boxName : "+box.getBoxName());
		File newFile=new File();
		newFile.setCheckSum(checkSum);
		newFile.setFileName(fileName);
		newFile.setFileLocation(location);
		TagesManager tManager = new TagesManager(session);

		if(modDate!=null)
			newFile.setModefiedDate(modDate);

		FileManager Fmanager = new FileManager(session);
		newFile.addBoxes(box);
		Fmanager.save(newFile);
		System.out.println("the new file id:"+newFile.getFileId());
		box.addFiles(newFile);
		BoxManager Bmanager = new BoxManager(session);
		Bmanager.update(box);
		if(tagedFiles!=null){
			for(TagedFiles tagedFile : tagedFiles){
				Tages tag = new Tages(tagedFile);
				System.out.println(tag);
				System.out.println("tag : "+tag.getTag()+" " + tag.getTagType());
				newFile.addTag(tag);
				Fmanager.update(newFile);
				tManager.save(tag);
			}
		}
		session.flush();
		return newFile;
	}
	/**
	 * create new client in database
	 * @param username the client name
	 * @param pass client password
	 * @param email client email
	 * @param computerName the computer name of client
	 * @param path location of drop box folder
	 * @param boxName folder name
	 * @return
	 */
	public Client createNewClient(String username, String pass, String email,
			String computerName, String path, String boxName) {
		BoxManager Bmanager = new BoxManager(session);
		Client client=null;
		ClientManager Cmanager = new ClientManager(session);
		Box box1=null;
		if(boxName!=null){
			System.out.println("new client");
			client = new Client();
			client.setUserName(username);
			client.setPassword(pass);
			client.setUserEmail(email);
			box1=new Box();
			box1.setBoxProperty("all");
			box1.setBoxName(boxName);
			box1.addClients(client);
			client.addBoxes(box1);
			Bmanager.save(box1);
			Cmanager.save(client);
		}
		else{
			System.out.println("client exist");
			Query query = session.createQuery("from Client where user_name= '"+username+"'");
			List<Client> list = query.list();
			client = list.get(0);
		}
		Computer comp1=null;
		if(computerName!=null){
			comp1=new Computer();
			comp1.setComputerName(computerName);
			comp1.setLogStatus("on");
			comp1.setPath(path);
			client.addComputers(comp1);
			Cmanager.update(client);
			ComputerManager Compmanager = new ComputerManager(session);	
			Compmanager.save(comp1);
		}

		session.flush();
		return client;
	}
	/**
	 * 
	 * @param client instance of client
	 * @return instance of client by ID from DB in case changes occur
	 */
	public Client regetClient(Client client){
		List<Client> clientList = getClient2("from Client where userId= '"+client.getUserId()+"'");
		return clientList.get(0);
	}
	/**
	 * add new Box to DB
	 * @param boxName folder name
	 * @param user client that send the message
	 */
	public void newBox(String boxName, Client user) {
		Box box=new Box();
		box.setBoxName(boxName);
		box.setBoxProperty("all");
		box.addClients(user);
		user.addBoxes(box);
		BoxManager bManager=new BoxManager(session);
		ClientManager cMenager = new ClientManager(session);
		cMenager.update(user);
		bManager.save(box);
		session.flush();

	}

	/**
	 * get folder from DB
	 * @param user client that send the message
	 * @param boxName folder name
	 * @return Box instance
	 */
	public Box getBox(Client user, String boxName) {
		Set<Box> boxes = user.getBoxes();
		for(Box b : boxes){
			if(b.getBoxName().equals(boxName))
				return b;
		}
		return null;
	}
	/**
	 * add new folder to client
	 * @param client to Client instance
	 * @param box folder to add
	 */
	public void addBoxToClient(Client client, Box box) {
		ClientManager cManager = new ClientManager(session);
		BoxManager bManager = new BoxManager(session);
		client.addBoxes(box);
		cManager.update(client);
		box.addClients(client);
		bManager.update(box);
		session.flush();
	}
	/**
	 * change tag list of file
	 * @param file File instance
	 * @param allTages list of new tags for the file
	 */
	public void changeTags(File file, ArrayList<TagedFiles> allTages) {
		file.getTages().clear();
		TagesManager tManager = new TagesManager(session);
		if(allTages!=null){
			for(TagedFiles tagedFile : allTages){
				Tages tag = new Tages(tagedFile);
				System.out.println(tag);
				System.out.println("tag : "+tag.getTag()+" " + tag.getTagType());
				file.addTag(tag);
				tManager.save(tag);
			}
		}

		session.flush();
	}
	/**
	 * renaming file in DB
	 * @param file File instance 
	 * @param fileName new file name
	 */
	public void renameFile(File file,String fileName) {
		file.setFileName(fileName);
		FileManager fManager = new FileManager(session);
		fManager.update(file);
		session.flush();
	}

}
